import dbus, gobject, avahi
from dbus import DBusException
from dbus.mainloop.glib import DBusGMainLoop
import logging

class AvahiSearch:
    def __init__(self, type, domain='local', flags=dbus.UInt32(0), 
            protocol=avahi.PROTO_UNSPEC, interface=avahi.IF_UNSPEC, 
            mainloop=DBusGMainLoop, callback=None):
        self.loop = mainloop()
        self.bus = dbus.SystemBus(mainloop=self.loop)
        self.server = dbus.Interface( self.bus.get_object(avahi.DBUS_NAME, 
            avahi.DBUS_PATH_SERVER), avahi.DBUS_INTERFACE_SERVER)

        self.type = type
        self.domain = domain
        self.flags = flags
        self.protocol = protocol
        self.interface = interface
        self.callback = callback
        # init
        self._register()

    def _register(self):
        self.sbrowser = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, 
                self.server.ServiceBrowserNew(self.interface, self.protocol,
                    self.type, self.domain, self.flags)),
                avahi.DBUS_INTERFACE_SERVICE_BROWSER)

        self.sbrowser.connect_to_signal("ItemNew", self._firsthandler)

    def register_service_handler(self, callback):
        # FIXME: check if callback has proper interface
        self.callback = callback

    def _firsthandler(self, interface, protocol, name, stype, domain, flags):
        # FIXME: do some checking
        if False and flags & avahi.LOOKUP_RESULT_LOCAL: # disabled for now,
        # for testing
                # local service, skip
                print 'found local service: %s %s' % (name, stype)
                pass
        else:
            self.server.ResolveService(interface, protocol, name, stype, 
                domain, avahi.PROTO_UNSPEC, dbus.UInt32(0), 
                reply_handler=self._finalhandler, error_handler=self._errorhandler)


    def _errorhandler(self, *args):
        logging.warning(str(args))
        print args

    def _finalhandler(self, *args):
        if self.callback is not None:
            self.callback(args[2],args[5],args[7],args[8])

